package com.eastseeway.radioproject.radio;

import android.app.Application;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.eastseeway.radioproject.base.BaseViewModel;
import com.eastseeway.radioproject.base.Const;
import com.eastseeway.radioproject.entities.BaseResponse;
import com.eastseeway.radioproject.entities.BaseTCPBean;
import com.eastseeway.radioproject.entities.Bean1FromHandle;
import com.eastseeway.radioproject.entities.BeanToBottomBoard;
import com.eastseeway.radioproject.entities.BeanToEnergyBoard;
import com.eastseeway.radioproject.entities.BeanToNegativePressureBoard;
import com.eastseeway.radioproject.entities.BottomBoardFunctionCode;
import com.eastseeway.radioproject.entities.ElectrodeInfoBean;
import com.eastseeway.radioproject.entities.OperationParams;
import com.eastseeway.radioproject.entities.UserInfo;
import com.eastseeway.radioproject.utils.ByteUtil;
import com.eastseeway.radioproject.utils.CommandGenerator;
import com.eastseeway.radioproject.utils.SPHelper;
import com.eastseeway.radioproject.utils.StructTransUtil;
import com.eastseeway.radioproject.utils.TimeUtils;
import com.google.gson.Gson;

import org.apache.commons.collections4.splitmap.AbstractIterableGetMapDecorator;

import java.nio.ByteBuffer;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import struct.StructException;

public class HandleRadioViewModel extends BaseViewModel<HandleRadioRepository> {
    //  提示信息 toast
    private final MutableLiveData<String> toastInfo = new MutableLiveData<>();
    private final MutableLiveData<String> info = new MutableLiveData<>();
//    提示信息 底部的文本
    //    频率
    private final MutableLiveData<Byte> frequency = new MutableLiveData<>((byte) 1);
    //   默认皮肤吸附压力以及压力值索引
    private final MutableLiveData<Integer> skinPressure = new MutableLiveData<>(-30);
    private final MutableLiveData<Integer> skinPressurePosition = new MutableLiveData<>(0);
    //    刺入深度以及深度值索引 界面显示上保留一位小数，但是内部存储时会*10，
    private final MutableLiveData<Byte> depth = new MutableLiveData<>((byte) 4);
    private final MutableLiveData<Integer> depthPosition = new MutableLiveData<>(0);
    //  断续模式下相关参数
    private final MutableLiveData<Integer> idp = new MutableLiveData<>(6);
    private final MutableLiveData<Integer> idhp = new MutableLiveData<>(40);
    private final MutableLiveData<Integer> idlp = new MutableLiveData<>(60);
    //  能量输出持续时长以及索引
    private final MutableLiveData<Short> continuousDischargePeriod = new MutableLiveData<>((short) 0);
    private final MutableLiveData<Integer> continuousDischargePosition = new MutableLiveData<>(0);
    //  剩余次数
    private final MutableLiveData<Short> shengyucishu = new MutableLiveData<>((short) 0);
    private LiveData<List<OperationParams>> operationParamsList = new MutableLiveData<>();
//    是否待机状态 待机状态可以调节参数 非待机状态不可调节参数
    private final MutableLiveData<Boolean> isStandByState = new MutableLiveData<>(true);
//    非待机状态下，是工作状态，还是准备状态
    private final MutableLiveData<Boolean> isWorkingState = new MutableLiveData<>(false);
    private final MutableLiveData<Boolean> isIntermittentMode = new MutableLiveData<>(false);
    //    是否预置模式
    private final MutableLiveData<Boolean> isPreMode = new MutableLiveData<>(false);
    //    输出能量MJ和J进行单位换算
    private final MutableLiveData<Boolean> isMJ = new MutableLiveData<>(true);
    byte energy = 5;
    public HandleRadioViewModel(@NonNull Application application) {
        super(application);
    }
    @Override
    protected HandleRadioRepository setRepository() {
        return new HandleRadioRepository();
    }

    void sendHandleCommand() {
        try {
            byte[] handleCommand = CommandGenerator.commandData1ToHandle1(Const.ADDRESS_TO_HANDLE_1_DATA_1, getFrequency().getValue(), energy, getDepth().getValue(),
                    (byte) (getSkinPressure().getValue()-0), getContinuousDischargePeriod().getValue(), getIdp().getValue().byteValue(), getIdhp().getValue().byteValue(),
                    getIdlp().getValue().byteValue(), getIsWorkingState().getValue(), getIsIntermittentMode().getValue(), shengyucishu.getValue());
//            Log.e("12121", "sendHandleCommand: 频率："+getFrequency().getValue()+";depth:"+getDepth().getValue()+";skinPressure:"+((getSkinPressure().getValue()-0))+";连续放电周期："+getContinuousDischargePeriod().getValue()+
//                    ";idp："+getIdp().getValue()+";idhp："+getIdhp().getValue()+";idlp："+getIdlp().getValue()+";work state："
//                    +getIsWorkingState().getValue()+";断续模式："+getIsIntermittentMode().getValue()+";剩余次数："+shengyucishu.getValue()+";");
            sendMessage(handleCommand);
            saveDataToFile("p:handle command "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new Bean1FromHandle(), handleCommand)));
        } catch (StructException e) {
            throw new RuntimeException(e);
        }
    }

    void sendPreCommand() {
        try {
            String vBusValue = mRepository.getVBusValue("1" + frequency.getValue() + energy);
            if (vBusValue == null) {
                vBusValue = "8";
            }
            float vBusVoltage = Float.parseFloat(vBusValue);

            byte[] commandToBottomBoard = CommandGenerator.command2BottomBoard(Const.ADDRESS_TO_BOTTOM_BOARD, BottomBoardFunctionCode.cmd_bottombrd_Vbus_Set, (short) (vBusVoltage * 100));

            byte[] commandToEnergyBoard = CommandGenerator.commandToEnergyBoard(Const.ADDRESS_TO_ENERGY_BOARD, getFrequency().getValue(),getIsIntermittentMode().getValue(), getIsStandByState().getValue(), getIdp().getValue());

            byte[] commandToNegativePressureBoard = CommandGenerator.command2NegativePressureBoard(Const.ADDRESS_TO_NEGATIVE_PRESSURE_BOARD, getCorrectedPressure(), 0, 0, 0);

//            Log.e("12121", "PreCommand: vBus"+vBusVoltage+";频率："+getFrequency().getValue()+";是否断续："+getIsIntermittentMode().getValue()+";是否待机:"+getIsStandByState().getValue()+";能量:"+energy+";idp:"+getIdp().getValue()+";负压"+getCorrectedPressure());
            ByteBuffer buffer = ByteBuffer.allocate(commandToEnergyBoard.length + commandToBottomBoard.length + commandToNegativePressureBoard.length);
            buffer.put(commandToEnergyBoard);
            buffer.put(commandToBottomBoard);
            buffer.put(commandToNegativePressureBoard);
            sendMessage(buffer.array());


            saveDataToFile("p:pre command ToBottomBoard "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToBottomBoard(), commandToBottomBoard)));
            saveDataToFile("p:pre command ToEnergyBoard "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToEnergyBoard(), commandToEnergyBoard)));
            saveDataToFile("p:pre command ToPressureBoard "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToNegativePressureBoard(), commandToNegativePressureBoard)));

        } catch (StructException e) {
            throw new RuntimeException(e);
        }
    }

//    恢复初始状态
    void resetState() {
        try  {
            byte[] commandToBottomBoard = CommandGenerator.command2BottomBoard(Const.ADDRESS_TO_BOTTOM_BOARD, BottomBoardFunctionCode.cmd_bottombrd_Vbus_Set, (short) 0);
            byte[] commandToEnergyBoard = CommandGenerator.commandToEnergyBoard(Const.ADDRESS_TO_ENERGY_BOARD, getFrequency().getValue(),getIsIntermittentMode().getValue(), true, getIdp().getValue());
            byte[] commandToNegativePressureBoard = CommandGenerator.command2NegativePressureBoard(Const.ADDRESS_TO_NEGATIVE_PRESSURE_BOARD, -5 *100, 0, 0, 0);
            byte[] handleCommand = CommandGenerator.commandData1ToHandle1(Const.ADDRESS_TO_HANDLE_1_DATA_1, getFrequency().getValue(), energy, getDepth().getValue(),
                    (byte) (0), getContinuousDischargePeriod().getValue(), getIdp().getValue().byteValue(), getIdhp().getValue().byteValue(),
                    getIdlp().getValue().byteValue(), false, getIsIntermittentMode().getValue(), shengyucishu.getValue());

            sendMessage(commandToBottomBoard);
            sendMessage(commandToEnergyBoard);
            sendMessage(commandToNegativePressureBoard);
            sendMessage(handleCommand);

            saveDataToFile("p:reset state ToBottomBoard "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToBottomBoard(),commandToBottomBoard)));
            saveDataToFile("p:reset state ToEnergyBoard "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToEnergyBoard(),commandToEnergyBoard)));
            saveDataToFile("p:reset state ToHandle "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new Bean1FromHandle(),handleCommand)));
            saveDataToFile("p:reset state ToPressureBoard "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToNegativePressureBoard(),commandToNegativePressureBoard)));

        } catch (StructException e) {
            throw new RuntimeException(e);
        }
    }

    void saveParamsToFile() {
        saveDataToFile(getCurrentParams());
    }

    void saveDataToFile(String data){
        mRepository.saveDataToFile(data);
    }

    String getCurrentParams(){
        OperationParams operationParams = new OperationParams(
                "",
                SPHelper.getCurrentUserInfo(getApplication()).getName(),
                0,
                TimeUtils.getCurrentTime(TimeUtils.FORMAT_DATE_TIME_FULL1),
                false,
                true,
                getFrequency().getValue(),
                energy,
                getSkinPressure().getValue().byteValue(),
                getSkinPressurePosition().getValue(),
                getDepth().getValue(),
                getDepthPosition().getValue(),
                (byte) 0,
                getIsIntermittentMode().getValue(),
                getIdp().getValue().byteValue(),
                getIdhp().getValue().byteValue(),
                getIdlp().getValue().byteValue(),
                getContinuousDischargePeriod().getValue().shortValue(),
                getContinuousDischargePosition().getValue(),
                shengyucishu.getValue()
        );
        return new Gson().toJson(operationParams);

    }

    public void setEnergy(byte energy) {
        this.energy = energy;
//        energyLiveData.setValue(energy);
    }

    public byte getEnergy() {
        return energy;
    }

    //    保存快捷操作参数
    void saveQuickOperationParam(UserInfo userInfo, int position) {
        OperationParams operationParams = new OperationParams(
                CommandGenerator.generateId(userInfo.getId(), true, position),
                userInfo.getName(),
                position,
                TimeUtils.getCurrentTime(TimeUtils.FORMAT_DATE_TIME_FULL1),
                false,
                true,
                getFrequency().getValue(),
                energy,
                getSkinPressure().getValue().byteValue(),
                getSkinPressurePosition().getValue(),
                getDepth().getValue(),
                getDepthPosition().getValue(),
                (byte) 0,
                getIsIntermittentMode().getValue(),
                getIdp().getValue().byteValue(),
                getIdhp().getValue().byteValue(),
                getIdlp().getValue().byteValue(),
                getContinuousDischargePeriod().getValue(),
                getContinuousDischargePosition().getValue(),
                shengyucishu.getValue()
        );
//        Log.e("12121", "saveQuickOperationParam " + new Gson().toJson(operationParams));
        mRepository.updateOperationParams(operationParams);
    }

    void queryOperationParams(String username) {
        operationParamsList = mRepository.queryOperationParams(username);
    }

    public LiveData<List<OperationParams>> getOperationParamsList() {
        return operationParamsList;
    }

    public MutableLiveData<String> getToastInfo() {
        return toastInfo;
    }

    public MutableLiveData<Integer> getSkinPressure() {return skinPressure;}

    public MutableLiveData<Integer> getSkinPressurePosition() {return skinPressurePosition;}

    public MutableLiveData<Byte> getDepth() {
        return depth;
    }

    public MutableLiveData<Short> getContinuousDischargePeriod() {return continuousDischargePeriod;}

    public MutableLiveData<Integer> getIdp() {return idp;}

    public MutableLiveData<Integer> getIdhp() {
        return idhp;
    }

    public MutableLiveData<Integer> getIdlp() {
        return idlp;
    }

    public MutableLiveData<Boolean> getIsIntermittentMode() {
        return isIntermittentMode;
    }

    public MutableLiveData<Integer> getContinuousDischargePosition() {return continuousDischargePosition;}

    public MutableLiveData<Integer> getDepthPosition() {return depthPosition;}

    public void changeFrequency() {
        playSound();
        frequency.setValue(frequency.getValue() == 1 ? (byte) 2 : (byte) 1);
        saveDataToFile("p:changeFrequency :"+frequency.getValue());
    }

    public MutableLiveData<Byte> getFrequency() {return frequency;}

    public void changeWorkState() {
        this.isStandByState.setValue(Boolean.FALSE.equals(getIsStandByState().getValue()));
    }

    public MutableLiveData<Boolean> getIsStandByState() {return isStandByState;}

    public MutableLiveData<Boolean> getIsWorkingState() {return isWorkingState;}

    public MutableLiveData<Short> getShengyucishu() {
        return shengyucishu;
    }

    public MutableLiveData<String> getInfo() {
        return info;
    }

    public MutableLiveData<Boolean> getIsPreMode() {return isPreMode;}

    public void replaceElectrode() {
        try {
            byte[] bytes = CommandGenerator.commandReplaceElectrode(Const.ADDRESS_TO_HANDLE_1_DATA_1);
            sendMessage(bytes);
        } catch (StructException e) {
            throw new RuntimeException(e);
        }
    }

    public void checkElectrode(String deviceid) {
        mRepository.checkElectrode(deviceid).enqueue(new Callback<BaseResponse<ElectrodeInfoBean>>() {
            @Override
            public void onResponse(Call<BaseResponse<ElectrodeInfoBean>> call, Response<BaseResponse<ElectrodeInfoBean>> response) {

            }

            @Override
            public void onFailure(Call<BaseResponse<ElectrodeInfoBean>> call, Throwable throwable) {

            }
        });
    }

    public void changeEnergyUnit(){
        isMJ.setValue(Boolean.FALSE.equals(isMJ.getValue()));
    }

    public MutableLiveData<Boolean> getIsMJ() {
        return isMJ;
    }

    public int getCorrectedPressure(){
        if (getSkinPressure().getValue() == 0) {
            return -5 * 100;
        }else {
            int pressureOffset = SPHelper.getPressureOffset(getApplication());
            return (getSkinPressure().getValue() - pressureOffset) * 100 ;
        }

    }
}
